home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / file / managers / mc-3.2 / mc-3 / mc-3.2.1 / vfs / tcputil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-17  |  5.6 KB  |  268 lines

  1. /* Server for the Midnight Commander Virtual File System.
  2.    Routines for the tcp connection, includes the primitive rpc routines.
  3.    
  4.    Copyright (C) 1995, 1996 Miguel de Icaza
  5.    
  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2 of the License, or
  9.    (at your option) any later version.
  10.    
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19. #include <config.h>
  20. #include <unistd.h>
  21. #include <stdlib.h>
  22. #include <stdarg.h>
  23. #include <stdio.h>
  24. #include <signal.h>
  25. #include <pwd.h>
  26. #include <sys/types.h>
  27. #include <netdb.h>
  28. #include <sys/socket.h>
  29. #include <netinet/in.h>
  30. #include <arpa/inet.h>
  31. #include <malloc.h>
  32.  
  33. #ifdef HAVE_PMAP_SET
  34. #include <rpc/rpc.h>
  35. #include <rpc/pmap_prot.h>
  36. #ifdef HAVE_RPC_PMAP_CLNT_H
  37. #include <rpc/pmap_clnt.h>
  38. #endif
  39. #endif
  40.  
  41. #ifdef USE_TERMNET
  42. #include <termnet.h>
  43. #endif
  44.  
  45. #include <signal.h>
  46. #include <errno.h>
  47. #include "tcputil.h"
  48. #include "../src/dialog.h"    /* for message () */
  49. #include "../src/mem.h"        /* for bcopy */
  50. #include "../src/util.h"    /* for unix_error_string */
  51. #include "../src/mad.h"
  52. #include "mcfs.h"        /* for mcserver_port definition */
  53.  
  54. #define CHECK_SIG_PIPE(sock) if (got_sigpipe) \
  55.      { tcp_invalidate_socket (sock); return got_sigpipe = 0; }
  56.  
  57. extern void tcp_invalidate_socket (int);
  58.  
  59. int got_sigpipe;
  60.  
  61. /* Reads a block on dest for len bytes from sock */
  62. /* Returns a boolean indicating the success status */
  63. int socket_read_block (int sock, char *dest, int len)
  64. {
  65.     int nread, n;
  66.  
  67.     for (nread = 0; nread < len;){
  68.     n = read (sock, dest+nread, len-nread);
  69.     if (n <= 0){
  70.         tcp_invalidate_socket (sock);
  71.         return 0;
  72.     }
  73.     nread += n;
  74.     }
  75.     return 1;
  76. }
  77.  
  78. int socket_write_block (int sock, char *buffer, int len)
  79. {
  80.     int left, status;
  81.  
  82.     for (left = len; left > 0;){
  83.     status = write (sock, buffer, left);
  84.     CHECK_SIG_PIPE (sock);
  85.     if (status < 0)
  86.         return 0;
  87.     left -= status;
  88.     buffer += status;
  89.     }
  90.     return 1;
  91. }
  92.  
  93. int send_string (int sock, char *string)
  94. {
  95.     return socket_write_block (sock, string, strlen (string));
  96. }
  97.  
  98. int rpc_send (int sock, ...)
  99. {
  100.     long int tmp, len, cmd;
  101.     char *text;
  102.     va_list ap;
  103.  
  104.     va_start (ap, sock);
  105.  
  106.     for (;;){
  107.     cmd = va_arg (ap, int);
  108.     switch (cmd){
  109.     case RPC_END:
  110.         va_end (ap);
  111.         return 1;
  112.  
  113.     case RPC_INT:
  114.         tmp = htonl (va_arg (ap, int));
  115.         write (sock, &tmp, sizeof (tmp));
  116.         CHECK_SIG_PIPE (sock);
  117.         break;
  118.  
  119.     case RPC_STRING:
  120.         text = va_arg (ap, char *);
  121.         len = strlen (text);
  122.         tmp = htonl (len);
  123.         write (sock, &tmp, sizeof (tmp));
  124.         CHECK_SIG_PIPE (sock);
  125.         write (sock, text, len);
  126.         CHECK_SIG_PIPE (sock);
  127.         break;        
  128.  
  129.     case RPC_BLOCK:
  130.         len = va_arg (ap, int);
  131.         text = va_arg (ap, char *);
  132.         tmp = htonl (len);
  133.         write (sock, text, len);
  134.         CHECK_SIG_PIPE (sock);
  135.         break;
  136.  
  137.     default:
  138.         fprintf (stderr, "Unknown rpc message\n");
  139.         abort ();
  140.     }
  141.     }
  142. }
  143.  
  144. typedef struct sock_callback_t {
  145.     int  sock;
  146.     void (*cback)(int);
  147.     struct sock_callback_t *link;
  148. } sock_callback_t;
  149.  
  150. sock_callback_t *sock_callbacks = 0;
  151.  
  152. static void check_hooks (int sock)
  153. {
  154.     sock_callback_t *callback, *prev;
  155.  
  156.     for (prev=callback = sock_callbacks; callback; callback = callback->link){
  157.     if (callback->sock != sock){
  158.         prev = callback;
  159.         continue;
  160.     }
  161.     callback->sock = -1;
  162.     (callback->cback)(sock);
  163.     if (callback == sock_callbacks){
  164.         sock_callbacks = callback->link;
  165.     } else {
  166.         prev->link = callback->link;
  167.     }
  168.     free (callback);
  169.     return;
  170.     }
  171. }
  172.  
  173. int rpc_get (int sock, ...)
  174. {
  175.     long int tmp, len;
  176.     char *text, **str_dest;
  177.     int  *dest, cmd;
  178.     va_list ap;
  179.  
  180.     va_start (ap, sock);
  181.  
  182.     check_hooks (sock);
  183.  
  184.     for (;;){
  185.     cmd = va_arg (ap, int);
  186.     switch (cmd){
  187.     case RPC_END:
  188.         va_end (ap);
  189.         return 1;
  190.  
  191.     case RPC_INT:
  192.         if (socket_read_block (sock, (char *) &tmp, sizeof (tmp)) == 0)
  193.         return 0;
  194.         dest = va_arg (ap, int *);
  195.         *dest = ntohl (tmp);
  196.         break;
  197.  
  198.         /* returns an allocated string */
  199.     case RPC_STRING:
  200.         if (socket_read_block (sock, (char *)&tmp, sizeof (tmp)) == 0)
  201.         return 0;
  202.         len = ntohl (tmp);
  203.         text = malloc (len+1);
  204.         if (socket_read_block (sock, text, len) == 0)
  205.         return 0;
  206.         str_dest = va_arg (ap, char **);
  207.         *str_dest = text;
  208.         text [len] = 0;
  209.         break;        
  210.  
  211.     case RPC_BLOCK:
  212.         len = va_arg (ap, int);
  213.         text = va_arg (ap, char *);
  214.         if (socket_read_block (sock, text, len) == 0)
  215.         return 0;
  216.         break;
  217.  
  218.     default:
  219.         fprintf (stderr, "Unknown rpc message\n");
  220.         abort ();
  221.     }
  222.     }
  223. }
  224.  
  225. void rpc_add_get_callback (int sock, void (*cback)(int))
  226. {
  227.     sock_callback_t *new;
  228.  
  229.     new = malloc (sizeof (sock_callback_t));
  230.     new->cback = cback;
  231.     new->sock = sock;
  232.     new->link = sock_callbacks;
  233.     sock_callbacks = new;
  234. }
  235.  
  236. #ifdef IS_AIX
  237. static void sig_pipe (int unused)
  238. #else
  239. static void sig_pipe (void)
  240. #endif
  241. {
  242.     got_sigpipe = 1;
  243.     signal (SIGPIPE, sig_pipe);    /* Reset the signal handler */
  244. }
  245.  
  246. void tcp_init (void)
  247. {
  248.     got_sigpipe = 0;
  249.     signal (SIGPIPE, sig_pipe);
  250. }
  251.  
  252. int get_remote_port (struct sockaddr_in *sin)
  253. {
  254.     int port;
  255.     
  256. #ifdef HAVE_PMAP_GETPORT
  257.     port = pmap_getport (sin, RPC_PROGNUM, RPC_PROGVER, IPPROTO_TCP);
  258.     if (port == 0)
  259.     return mcserver_port;
  260.     else
  261.     return port;
  262. #else
  263.     return mcserver_port;
  264. #endif
  265. }
  266.  
  267.  
  268.